// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.api.ads.adwords.jaxws.utils.v201109_1;

import com.google.api.ads.adwords.jaxws.v201109_1.cm.ReportDefinition;
import com.google.api.ads.adwords.lib.client.AdWordsSession;
import com.google.api.ads.adwords.lib.utils.AdHocReportDownloadHelper;
import com.google.api.ads.adwords.lib.utils.DefinedReportDownloadHelper;
import com.google.api.ads.adwords.lib.utils.ReportDownloadResponse;
import com.google.api.ads.adwords.lib.utils.ReportException;
import com.google.api.ads.common.lib.soap.jaxws.JaxBSerializer;
import com.google.common.annotations.VisibleForTesting;

import javax.xml.namespace.QName;

/**
 * Reports are fetched synchronously like in the following code:
 *
 * <pre>
 *<code>new ReportDownloader(adWordsSession).downloadReport(reportDefinition);
 *</code>
 *</pre>
 *
 * The {@code adWordsSession} is used to authenticate the request against the
 * {@code reportDownloadUrl}.
 *
 * @author Adam Rogal
 * @author Kevin Winter
 */
public final class ReportDownloader {

  /** The version to append to url for Ad Hoc report downloads. */
  private static final String VERSION = "v201109_1";

  private final AdWordsSession session;
  private final AdHocReportDownloadHelper adHocReportDownloadHelper;
  private final DefinedReportDownloadHelper definedReportDownloadHelper;
  private final JaxBSerializer<ReportDefinition> serializer;

  /**
   * Constructs a {@link ReportDownloader}.
   *
   * @param session AdWordsSession to use to make report download requests.
   */
  public ReportDownloader(AdWordsSession session) {
    this.adHocReportDownloadHelper = new AdHocReportDownloadHelper(session, VERSION);
    this.definedReportDownloadHelper = new DefinedReportDownloadHelper(session, VERSION);
    this.serializer = new JaxBSerializer<ReportDefinition>(ReportDefinition.class, new QName(
        "reportDefinition"));
    this.session = session;
  }

  /**
   * Downloads a report and returns a ReportDownloadResponse with the results.
   *
   * @param reportDefinitionId to download a report for.
   * @return {@link ReportDownloadResponse} When HTTP request completes. On success, the
   *         outputStream will be flushed and closed.
   * @throws ReportException If there is any issue making HTTP request with server.
   * @deprecated use {@link ReportDownloader#downloadReport(ReportDefinition)}.
   */
  @Deprecated
  public ReportDownloadResponse downloadReport(long reportDefinitionId) throws ReportException {
    return definedReportDownloadHelper.downloadReport(reportDefinitionId);
  }

  /**
   * Downloads a report and returns a ReportDownloadResponse with the results.
   *
   * @param reportDefinition to download a report for.
   * @return {@link ReportDownloadResponse} When HTTP request completes. On success, the
   *         outputStream will be flushed and closed.
   * @throws ReportException If there is any issue making HTTP request with server.
   */
  public ReportDownloadResponse downloadReport(ReportDefinition reportDefinition)
      throws ReportException {
    return adHocReportDownloadHelper.downloadReport(toXml(reportDefinition));
  }

  /**
   * Uses the built-in jaxws serializer to serialize the report and sanitize the results.
   *
   * @param reportDefinition to serialize
   * @return Sanitized XML for the report download.
   */
  @VisibleForTesting
  String toXml(ReportDefinition reportDefinition) {
    return serializer.serialize(reportDefinition);
  }
}
